package com.tebiecloud.act.server.configuration;

import com.tebiecloud.common.handler.CustomAccessDeniedHandler;
import com.tebiecloud.common.handler.CustomAuthenticationEntryPoint;
import com.tebiecloud.common.security.SecurityHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

/**
 * oauth2资源服务器配置
 * @Author: tebie
 * @Date: 2019-09-09 09:25
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        // 构建redis获取token服务类
        resources.tokenServices(SecurityHelper.buildRedisTokenServices(redisConnectionFactory));
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 配置session的创建策略，默认IF_REQUIRED：Spring Security只会在需要时创建一个HttpSession
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                // 地址认证规则配置
                .and()
                .authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll() // 监控端点内部放行
                .antMatchers("/feign/**").permitAll() // feign访问或无需身份认证w
                .anyRequest().authenticated() // 未指定地址均需认证

                // 认证鉴权错误处理，为了统一异常处理，每个资源服务器都应该加上
                .and()
                .exceptionHandling()
                .accessDeniedHandler(new CustomAccessDeniedHandler())
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())

                // 禁用csrf
                .and()
                .csrf().disable();
    }

}
